package com.literature.search.core.handler;

import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.NotPermissionException;
import com.literature.search.core.entity.R.AjaxError;
import com.literature.search.core.entity.R.AjaxJson;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.RedisConnectionFailureException;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;

/**
 * @Author: DangKong
 * @Date: 2023/3/1 14:25
 * @Description: 全局统一异常处理 捕获异常，产生异常时，统一返回错误信息
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
    /**
     * 全局异常拦截
     */
    @ExceptionHandler
    public AjaxJson handlerException(Exception e) {

        // 打印堆栈，以供调试 ( 仅在开发环境下打印 )
        e.printStackTrace(); //TODO 临时打印，后期删除

        // 记录日志信息
        AjaxJson aj = null;
        Throwable e2 = e.getCause();

        // ------------- 判断异常类型，提供个性化提示信息-------------------

        // 如果是未登录异常
        if (e instanceof NotLoginException) {
            aj = AjaxJson.getNotLogin();
        }
        // 如果是权限异常
        else if (e instanceof NotPermissionException) {
            NotPermissionException ee = (NotPermissionException) e;
            aj = AjaxJson.getNotJur("无此权限：" + ee.getPermission());
        }
        // 如果是AjaxError，则获取其具体code码
        else if (e instanceof AjaxError) {
            AjaxError ee = (AjaxError) e;
            aj = AjaxJson.get(ee.getCode(), ee.getMessage());
        }
        // 如果是redis连接异常 ( 由于redis连接异常，系统已经无法正常工作，所以此处需要立即返回 )
        else if (e instanceof RedisConnectionFailureException) {
            aj = AjaxJson.getError("Redis异常，请检查连接信息");
            return aj;
        } else if (e instanceof ConstraintViolationException) { //处理ConstraintViolationException异常
            // 拼接错误
            StringBuilder detailMessage = new StringBuilder();
            for (ConstraintViolation<?> constraintViolation : ((ConstraintViolationException) e).getConstraintViolations()) {
                // 使用 ; 分隔多个错误
                if (detailMessage.length() > 0) {
                    detailMessage.append(";");
                }
                // 拼接内容到其中
                detailMessage.append(constraintViolation.getMessage());
            }
            // 包装 Result 结果
            aj = AjaxJson.getError(detailMessage.toString());
            return aj;
        } else if (e instanceof MethodArgumentNotValidException) {
            BindingResult bindingResult = ((MethodArgumentNotValidException) e).getBindingResult(); // 获取BindingResult
            String message = null;
            if (bindingResult.hasErrors()) { // 判断BindingResult是否有错误
                FieldError fieldError = bindingResult.getFieldError(); // 获取错误信息
                if (fieldError != null) {
                    message = fieldError.getDefaultMessage();
                }
            }
            aj = AjaxJson.getError(message);
            return aj;
        } else if(e instanceof BindException){
            BindingResult bindingResult = ((BindException) e).getBindingResult(); // 获取BindingResult
            String message = null;
            if (bindingResult.hasErrors()) { // 判断BindingResult是否有错误
                FieldError fieldError = bindingResult.getFieldError(); // 获取错误信息
                if (fieldError != null) {
                    message = fieldError.getDefaultMessage();
                }
            }
            aj = AjaxJson.getError(message);
            return aj;
        }
        // 普通异常输出：500 + 异常信息
        else {
            aj = AjaxJson.getError(e.getMessage());
        }

        return aj;
    }


}
